#include "sobelfilter.h"


struct _sobel_arr SobelFilter::sobel_arr(QImage *qin){
    in_image=qin;
    struct _sobel_arr sob_sob_arr;
    k_cols=3;
    k_rows=3;
    kernel=new double[k_rows*k_cols];
    kernel[0]=1.0;
    kernel[1]=2.0;
    kernel[2]=1.0;
    kernel[3]=0.0;
    kernel[4]=0.0;
    kernel[5]=0.0;
    kernel[6]=-1.0;
    kernel[7]=-2.0;
    kernel[8]=-1.0;
    int cols=qin->width();
    int rows=qin->height();    
    struct image imggy=convolve_img(qin);
    kernel[0]=1.0;
    kernel[1]=0.0;
    kernel[2]=-1.0;
    kernel[3]=2.0;
    kernel[4]=0.0;
    kernel[5]=-2.0;
    kernel[6]=1.0;
    kernel[7]=0.0;
    kernel[8]=-1.0;
    struct image imggx=convolve_img(qin);
    sob_sob_arr.R=new int[cols*rows];
    sob_sob_arr.G=new int[cols*rows];
    sob_sob_arr.B=new int[cols*rows];
    sob_sob_arr.dirR=new double[cols*rows];
    sob_sob_arr.dirG=new double[cols*rows];
    sob_sob_arr.dirB=new double[cols*rows];
    int x,y,i;
    for(x=0;x<cols;x++)
        for(y=0;y<rows;y++){
            i=x+y*cols;
            sob_sob_arr.R[i]=(int)sqrt(imggx.R[i]*imggx.R[i]+imggy.R[i]*imggy.R[i]);
            sob_sob_arr.G[i]=(int)sqrt(imggx.G[i]*imggx.G[i]+imggy.G[i]*imggy.G[i]);
            sob_sob_arr.B[i]=(int)sqrt(imggx.B[i]*imggx.B[i]+imggy.B[i]*imggy.B[i]);
            sob_sob_arr.dirR[i]=atan(imggy.R[i]*1.0/imggx.R[i]);
            sob_sob_arr.dirG[i]=atan(imggy.G[i]*1.0/imggx.G[i]);
            sob_sob_arr.dirB[i]=atan(imggy.B[i]*1.0/imggx.B[i]);
    }
    delete [] imggx.R;
    delete [] imggx.G;
    delete [] imggx.B;
    delete [] imggy.R;
    delete [] imggy.G;
    delete [] imggy.B;
    return sob_sob_arr;

}

QImage SobelFilter::convolve(QImage *in_image, int mode)
{
   return convolve(in_image,mode,0);
}

QImage SobelFilter::convolve(QImage* in_image,int mode, double frac){
    this->in_image=in_image;
    k_cols=3;
    k_rows=3;
    kernel=new double[k_rows*k_cols];
    kernel[0]=1.0;
    kernel[1]=2.0;
    kernel[2]=1.0;
    kernel[3]=0.0;
    kernel[4]=0.0;
    kernel[5]=0.0;
    kernel[6]=-1.0;
    kernel[7]=-2.0;
    kernel[8]=-1.0;
    int cols=in_image->width();
    int rows=in_image->height();
    int *inputR=new int[cols*rows];
    int *inputG;
    int *inputB;
    int gray=in_image->isGrayscale();
    if(!(gray))
    {
        inputG=new int[cols*rows];
        inputB=new int[cols*rows];
    }
    for(int i=0;i<cols;i++)
        for(int j=0;j<rows;j++)
        {
            inputR[i+j*cols]=qRed(in_image->pixel(i,j));
            if(!(gray))
            {
            inputG[i+j*cols]=qGreen(in_image->pixel(i,j));
            inputB[i+j*cols]=qBlue(in_image->pixel(i,j));
            }
        }
    int* outputR=convolve(inputR);
    int* outputG;
    int* outputB;
    if(!(gray))
    {
        outputG=convolve(inputG);
        outputB=convolve(inputB);
    }
    kernel[0]=1.0;
    kernel[1]=0.0;
    kernel[2]=-1.0;
    kernel[3]=2.0;
    kernel[4]=0.0;
    kernel[5]=-2.0;
    kernel[6]=1.0;
    kernel[7]=0.0;
    kernel[8]=-1.0;
    int* outputR2=convolve(inputR);
    delete []inputR;
    int* outputG2;
    int* outputB2;
    if(!(gray))
    {
        outputG2=convolve(inputG);
        delete []inputG;
        outputB2=convolve(inputB);
        delete []inputB;
    }
    for(int x=0;x<cols;x++)
        for(int y=0;y<rows;y++){
            int i=x+y*cols;
            outputR[i]=(int)sqrt(outputR[i]*outputR[i]+outputR2[i]*outputR2[i]);
            if(!(gray))
            {
            outputG[i]=(int)sqrt(outputG[i]*outputG[i]+outputG2[i]*outputG2[i]);
            outputB[i]=(int)sqrt(outputB[i]*outputB[i]+outputB2[i]*outputB2[i]);
            }
    }
    delete [] outputR2;
    if(!(gray))
    {
        delete [] outputG2;
        delete [] outputB2;
    }
    if(gray)
    {
        return normalize(outputR,mode,frac);
    }
  return normalize(outputR,outputG,outputB,mode,frac);
}

QImage SobelFilter::convolve(QImage *in_image){

    this->in_image=in_image;
    k_cols=3;
    k_rows=3;
    kernel=new double[k_rows*k_cols];
    kernel[0]=1.0;
    kernel[1]=2.0;
    kernel[2]=1.0;
    kernel[3]=0.0;
    kernel[4]=0.0;
    kernel[5]=0.0;
    kernel[6]=-1.0;
    kernel[7]=-2.0;
    kernel[8]=-1.0;
    int cols=in_image->width();
    int rows=in_image->height();
    int *inputR=new int[cols*rows];
    int *inputG;
    int *inputB;
    int gray=in_image->isGrayscale();
    if(!(gray))
    {
        inputG=new int[cols*rows];
        inputB=new int[cols*rows];
    }
    for(int i=0;i<cols;i++)
        for(int j=0;j<rows;j++)
        {
            inputR[i+j*cols]=qRed(in_image->pixel(i,j));
            if(!(gray))
            {
            inputG[i+j*cols]=qGreen(in_image->pixel(i,j));
            inputB[i+j*cols]=qBlue(in_image->pixel(i,j));
            }
        }
    int* outputR=convolve(inputR);
    int* outputG;
    int* outputB;
    if(!(gray))
    {
        outputG=convolve(inputG);
        outputB=convolve(inputB);
    }
    kernel[0]=1.0;
    kernel[1]=0.0;
    kernel[2]=-1.0;
    kernel[3]=2.0;
    kernel[4]=0.0;
    kernel[5]=-2.0;
    kernel[6]=1.0;
    kernel[7]=0.0;
    kernel[8]=-1.0;
    int* outputR2=convolve(inputR);
    delete []inputR;
    int* outputG2;
    int* outputB2;
    if(!(gray))
    {
        outputG2=convolve(inputG);
        delete []inputG;
        outputB2=convolve(inputB);
        delete []inputB;
    }
    for(int x=0;x<cols;x++)
        for(int y=0;y<rows;y++){
            int i=x+y*cols;
            outputR[i]=(int)sqrt(outputR[i]*outputR[i]+outputR2[i]*outputR2[i]);
            if(!(gray))
            {
            outputG[i]=(int)sqrt(outputG[i]*outputG[i]+outputG2[i]*outputG2[i]);
            outputB[i]=(int)sqrt(outputB[i]*outputB[i]+outputB2[i]*outputB2[i]);
            }
    }
    delete [] outputR2;
    if(!(gray))
    {
        delete [] outputG2;
        delete [] outputB2;
    }
  QImage newimage(in_image->width(),in_image->height(),in_image->format());
  for(int i=0;i<cols;i++)
          for(int j=0;j<rows;j++)
          {
              int r=outputR[i+cols*j];
              if(r<0) r=0;
              if(r>255) r=255;
              if(!(gray))
              {
              int g=outputG[i+cols*j];
              if(g<0) g=0;
              if(g>255) g=255;
              int b=outputB[i+cols*j];
              if(b<0) b=0;
              if(b>255) b=255;
              newimage.setPixel(i,j,qRgb(r,g,b));
              }else
              newimage.setPixel(i,j,qRgb(r,r,r));
          }
  delete []outputR;
  if(!(gray))
  {
  delete []outputG;
  delete []outputB;
  }
  return newimage;
}

int * SobelFilter::convolve(int* input){
    return this->Filter::convolve(input);
}


int * SobelFilter::intelSobel(QImage *qin){
    this->in_image=qin;
    k_cols=3;
    k_rows=3;
    kernel=new double[k_rows*k_cols];
    kernel[0]=1.0;
    kernel[1]=2.0;
    kernel[2]=1.0;
    kernel[3]=0.0;
    kernel[4]=0.0;
    kernel[5]=0.0;
    kernel[6]=-1.0;
    kernel[7]=-2.0;
    kernel[8]=-1.0;
    int cols=qin->width();
    int rows=qin->height();
    int *input=new int[cols*rows];
    for(int i=0;i<cols;i++)
        for(int j=0;j<rows;j++)
            input[i+j*cols]=qRed(in_image->pixel(i,j));
    int *output=convolve(input);
    kernel[0]=1.0;
    kernel[1]=0.0;
    kernel[2]=-1.0;
    kernel[3]=2.0;
    kernel[4]=0.0;
    kernel[5]=-2.0;
    kernel[6]=1.0;
    kernel[7]=0.0;
    kernel[8]=-1.0;
    int *output2=convolve(input);
    delete []input;
    for(int x=0;x<cols;x++)
        for(int y=0;y<rows;y++){
            int i=x+y*cols;
            output[i]=(int)sqrt(output[i]*output[i]+output2[i]*output2[i]);
            }
    delete [] output2;
    return output;

}



SobelFilter::~SobelFilter(){
    delete [] kernel;
}
